#pragma execution_character_set("utf-8")
#include "udpsys.h"
#include <QString>
#include <iostream>
#include <QHostAddress>
#include <QNetworkInterface>
#include <QStringList>
#include <QUdpSocket>
#include <QTcpSocket>
using namespace std;

QStringList UdpSys::getLocalMacAddress()
{
    QStringList macList;
    QList<QNetworkInterface> lists = QNetworkInterface::allInterfaces();
    foreach(QNetworkInterface netitface,lists){
        if(netitface.name().contains("en") ||           // enp enx ena
                netitface.name().contains("eth") )
            macList.append(netitface.hardwareAddress());
    }
    return macList;
}

int UdpSys::getOrder(const QByteArray &datagram)
{
    return (quint8)datagram.at(0);
}

QString UdpSys::getCmdStr(const QByteArray &datagram)
{
    QByteArray headerArray;
    int len = datagram.length();
    if(len <= 8){
        return "";
    }else{
        int rawLen = (quint8)datagram[2];
        if(rawLen > len-8){
            rawLen = len-8;
        }
        headerArray = datagram.left(8+rawLen);
        return QString(headerArray.right(rawLen));
    }
}

QString UdpSys::getCmdOUtstr(const QByteArray &datagram)
{
    int len = datagram.length();
    int cmdLen = (quint8)datagram[2];
    int outLen = (quint8)datagram[6] + ((quint8)datagram[7])*256;

    if(len <= 8 + cmdLen){
        return "";
    }else{
        if(outLen > len-8-cmdLen){
            outLen = len-8-cmdLen;
        }
        return QString(datagram.mid(8+cmdLen, outLen));
    }
}

int UdpSys::getLeftStrLen(const QByteArray &datagram)
{
    int len = datagram.length();
    int cmdLen = (quint8)datagram[2];
    int outLen = (quint8)datagram[6] + ((quint8)datagram[7])*256;

    if(len >= 8+cmdLen+outLen){
        return len - 8 - cmdLen - outLen;
    }else{
        return 0;
    }
}

bool UdpSys::isCompletePack(const QByteArray &datagram)
{
    int len = datagram.length();
    if(len >= 8){
        int type = (quint8)datagram.at(0);
        if(type < CMD_STATUS || type > CMD_KILLALL){
            return false;
        }

        int cmdLen = (quint8)datagram[2];
        int outLen = (quint8)datagram[6] + ((quint8)datagram[7])*256;

        if(len >= 8+cmdLen+outLen){
            return true;
        }else{
            return false;
        }
    }else{
        return false;
    }
}

/* 获取命令执行时间，单位：秒
 * 对于服务端：命令超时时间
 * 对于客户端：命令已经执行的时间 */
int UdpSys::getTimes(const QByteArray &datagram)
{
    int times = (quint8)datagram[4] + ((quint8)datagram[5])*255;
    return times;
}

QString UdpSys::getDataRecvShow(const QByteArray &datagram)
{
    QString retStr;
    retStr.append(QString("cmd-0x%1 ").arg(QString::number((quint8)datagram[0], 16)));
    int len = (quint8)datagram[2] + ((quint8)datagram[3])*255;
    retStr.append(QString("len-%1 ").arg(len));
    len = datagram.length();
    retStr.append(QString("detail-'%1'").arg(datagram.right(len-8).data()));
    return retStr;
}

QString UdpSys::getHostIP(const QHostAddress &hostAddress)
{
    quint32 hostip = hostAddress.toIPv4Address();

    return QString("%1.%2.%3.%4")
            .arg((hostip&0xFF000000) >> 24)
            .arg((hostip&0x00FF0000) >> 16)
            .arg((hostip&0x0000FF00) >> 8)
            .arg((hostip&0x000000FF) >> 0);

//    QString rawIP = hostAddress.toString();
//    int index = rawIP.indexOf("192");
//    if(index >= 0 && index < rawIP.length()){
//        return rawIP.right(rawIP.length() - index);
//    }else{
//        return "127.0.0.1";
//    }
}

void UdpSys::getDevStatus(const QByteArray &datagram, int &cpuRate, int &memRate, int &cpuTemp, int &vdoTemp, int &hddTemp)
{
    int len = datagram.length();
    int cmdLen = static_cast<quint8>(datagram[2]);

    if(cmdLen > len){
        cmdLen = len;
    }
    cpuRate = 0;
    memRate = 0;
    cpuTemp = 0;
    if(cmdLen <= 0){

    }else{
        if(      cmdLen >= 6){
            cpuRate = static_cast<quint8>(datagram[8]) + static_cast<quint8>(datagram[9])*256;
            memRate = static_cast<quint8>(datagram[10]) + static_cast<quint8>(datagram[11])*256;
            cpuTemp = static_cast<quint16>(static_cast<quint8>(datagram[12]) + static_cast<quint8>(datagram[13])*256);
            if(cmdLen >= 8){
                vdoTemp = static_cast<quint8>(datagram[14]) + static_cast<quint8>(datagram[15])*256;
            }else{
                vdoTemp = 0;
            }
            if(cmdLen >= 10){
                hddTemp = static_cast<quint8>(datagram[16]) + static_cast<quint8>(datagram[17])*256;
            }else{
                hddTemp = 0;
            }
        }else if(cmdLen >= 4){
            cpuRate = static_cast<quint8>(datagram[8]) + static_cast<quint8>(datagram[9])*256;
            memRate = static_cast<quint8>(datagram[10]) + static_cast<quint8>(datagram[11])*256;
        }else if(cmdLen >= 2){
            cpuRate = static_cast<quint8>(datagram[8]) + static_cast<quint8>(datagram[9])*256;
        }


    }
}

void UdpSys::sendDataGram_toAddress(QUdpSocket *udpSocket, int comm_port, QString address,
                                    int cmdID, int timeOuts, QString cmdStr, QString outStr)
{
    QByteArray outArray =  outStr.toUtf8();
    QByteArray cmdArray =  cmdStr.toLatin1();
    if(cmdArray.length() > 255){
        cout << "Err, cmdStrlen: " << cmdArray.length() << endl;
        return;
    }
    if(outArray.length() > 10240){
        cout << "Err, outArray: " << outArray.length() << endl;
        return;
    }

    QHostAddress hostAddress;
    hostAddress.setAddress(address);
    QByteArray dataHeader;
    dataHeader.resize(8);
    dataHeader[0] = (quint8)cmdID;
    dataHeader[1] = 0;
    int cmdLen = cmdArray.length();
    dataHeader[2] = (quint8)(cmdLen%256);
    dataHeader[3] = 0;
    dataHeader[4] = (quint8)(timeOuts%256);
    dataHeader[5] = (quint8)(timeOuts/256);
    int outLen = outArray.length();
    dataHeader[6] = (quint8)(outLen%256);
    dataHeader[7] = (quint8)(outLen/256);

    QByteArray sendArray = dataHeader + cmdArray + outArray;
    int length_1 = udpSocket->writeDatagram(sendArray, sendArray.length(), hostAddress, comm_port);

    if(length_1 == sendArray.length()){
//        cout << "发送成功" << endl;
    }else{
        cout << "发送失败" << endl;
    }
}

bool UdpSys::sendDataGram_toAddress(QTcpSocket *tcpSocket, QString address, int cmdID, int timeOuts, QString cmdStr, QString outStr)
{
    QByteArray outArray =  outStr.toUtf8();
    QByteArray cmdArray =  cmdStr.toLatin1();
    if(cmdArray.length() > 255){
        cout << "Err, cmdStrlen: " << cmdArray.length() << endl;
        return false;
    }
    if(outArray.length() > 10240){
        cout << "Err, outArray: " << outArray.length() << endl;
        return false;
    }

    QHostAddress hostAddress;
    hostAddress.setAddress(address);
    QByteArray dataHeader;
    dataHeader.resize(8);
    dataHeader[0] = (quint8)cmdID;
    dataHeader[1] = 0;
    int cmdLen = cmdArray.length();
    dataHeader[2] = (quint8)(cmdLen%256);
    dataHeader[3] = 0;
    dataHeader[4] = (quint8)(timeOuts%256);
    dataHeader[5] = (quint8)(timeOuts/256);
    int outLen = outArray.length();
    dataHeader[6] = (quint8)(outLen%256);
    dataHeader[7] = (quint8)(outLen/256);

    QByteArray sendArray = dataHeader + cmdArray + outArray;

    int length_1 = static_cast<int>(tcpSocket->write(sendArray));
//    for(int i=0; i<sendArray.size(); i++){
//        if(i % 16 == 0)
//            std::cout << endl;
//        std::cout << (int)sendArray.at(i) << " ";
//    }
    if(length_1 == sendArray.length()){
        cout << "tcp write data len: " << length_1 << endl;
        return true;
    }else{
        cout << "tcp err send data len: " << length_1 <<endl;
        return false;
    }
}

void UdpSys::sendDevState_toAddress(QUdpSocket *udpSocket, int comm_port, QString address, int cpuRate, int memRate, int cpuTemp, QString outStr)
{
    QByteArray outArray =  outStr.toUtf8();
    if(outArray.length() > 10240){
        cout << "Err, outArray: " << outArray.length() << endl;
        return;
    }

    QHostAddress hostAddress;
    hostAddress.setAddress(address);
    QByteArray dataHeader;
    dataHeader.resize(14);
    dataHeader[0] = (quint8)CMD_STATUS;
    dataHeader[1] = 0;
    dataHeader[2] = 6;      // cmdLen
    dataHeader[3] = 0;
    dataHeader[4] = 0;
    dataHeader[5] = 0;
    int outLen = outArray.length();
    dataHeader[6] = (quint8)(outLen%256);
    dataHeader[7] = (quint8)(outLen/256);

    dataHeader[8]  = (quint8)(cpuRate%256);
    dataHeader[9]  = (quint8)(cpuRate/256);
    dataHeader[10] = (quint8)(memRate%256);
    dataHeader[11] = (quint8)(memRate/256);
    dataHeader[12] = (quint8)(cpuTemp & 0xff);
    dataHeader[13] = (quint8)((cpuTemp & 0xff00) >> 8);

    QByteArray sendArray = dataHeader + outArray;
    int length_1 = udpSocket->writeDatagram(sendArray, sendArray.length(), hostAddress, comm_port);

    if(length_1 == sendArray.length()){
//        cout << "发送成功" << endl;
    }else{
        cout << "发送失败" << endl;
    }
}

bool UdpSys::sendDevState_toAddress(QTcpSocket *tcpSocket, QString address, int cpuRate, int memRate, int cpuTemp, QString outStr)
{
    QByteArray outArray =  outStr.toUtf8();
    if(outArray.length() > 10240){
        cout << "Err, outArray: " << outArray.length() << endl;
        return false;
    }

    QHostAddress hostAddress;
    hostAddress.setAddress(address);
    QByteArray dataHeader;
    dataHeader.resize(14);
    dataHeader[0] = (quint8)CMD_STATUS;
    dataHeader[1] = 0;
    dataHeader[2] = 6;      // cmdLen
    dataHeader[3] = 0;
    dataHeader[4] = 0;
    dataHeader[5] = 0;
    int outLen = outArray.length();
    dataHeader[6] = (quint8)(outLen%256);
    dataHeader[7] = (quint8)(outLen/256);

    dataHeader[8]  = (quint8)(cpuRate%256);
    dataHeader[9]  = (quint8)(cpuRate/256);
    dataHeader[10] = (quint8)(memRate%256);
    dataHeader[11] = (quint8)(memRate/256);
    dataHeader[12] = (quint8)(cpuTemp & 0xff);
    dataHeader[13] = (quint8)((cpuTemp & 0xff00) >> 8);

    QByteArray sendArray = dataHeader + outArray;
    int length_1 = static_cast<int>(tcpSocket->write(sendArray));

    if(length_1 == sendArray.length()){
        cout << "tcp write state len: " << length_1 << endl;
        return true;
    }else{
        cout << "tcp err send state len: " << length_1 <<endl;
        return false;
    }
}
